﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using BlogEngine.Core;
using _4mvcBlog.Core;
using System.Web.Security;
using Newtonsoft.Json;

namespace _4mvcBlog.Controllers
{
    [HandleError(Master="Blog")]
    public class HomeController : BlogBaseController
    {
        public HomeController()
        {
            AddCategoriesViewData();
        }

        #region 首页

        public ActionResult Index(int? id)
        {
            if (BlogSettings.Instance.UseBlogNameInPageTitles)
            {
                PageTitle = BlogSettings.Instance.Description;
            }
            else
            {
                PageTitle = BlogSettings.Instance.Name;
            }
            AddMetaKeywords();
            base.AddMetaTag("description", Server.HtmlEncode(BlogSettings.Instance.Description));
            base.AddMetaTag("author", Server.HtmlEncode(BlogSettings.Instance.AuthorName));

            List<IPublishable> posts = BlogEngine.Core.Post.Posts
                .FindAll(delegate(Post p) { return p.IsVisible; })
                .ConvertAll(new Converter<Post, IPublishable>(delegate(Post p) { return p as IPublishable; }));

            int pageIndex = (id != null && id.HasValue && id.Value > 0) ? id.Value : 1;
            int pageSize = Math.Min(posts.Count, BlogSettings.Instance.PostsPerPage);
            int take = pageSize;
            int total = posts.Count;
            if ((pageIndex - 1) * pageSize >= total)
            {
                return ShowMsg("页码超出范围");
            }
            if (pageIndex * pageSize > total)
            {
                take = pageIndex * pageSize - total;
            }
            posts = posts.GetRange((pageIndex - 1) * pageSize, take);

            return View(posts.ToPagedList<IPublishable>(pageIndex, pageSize, total));
        }

        /// <summary>
        /// 把分类当做关键字添加到关键字meta标记中.
        /// </summary>
        private void AddMetaKeywords()
        {
            if (Category.Categories.Count > 0)
            {
                string[] categories = new string[Category.Categories.Count];
                for (int i = 0; i < Category.Categories.Count; i++)
                {
                    categories[i] = Category.Categories[i].Title;
                }
                base.AddMetaTag("keywords", Server.HtmlEncode(string.Join(",", categories)));
            }
        }

        #endregion

        #region 查看指定的Post
        /// <summary>
        /// 查看指定的Post
        /// </summary>
        [ActionName("Post")]
        public ActionResult ViewPostById(string id)
        {
            if (string.IsNullOrEmpty(id))
            {
                return ShowMsg("请指定要查看的Post的Id");
            }
            try
            {
                Guid guid = new Guid(id);
                Post post = Post.GetPost(guid);
                PageTitle = post.Title;
                GetCommentCookie();
                return View(post);
            }
            catch (Exception ex)
            {
                return ShowMsg(new List<string>() { ex.Message });
            }
        }

        /// <summary>
        /// 查看指定的Post
        /// </summary>
        [ActionName("PostBySlug")]
        public ActionResult ViewPostBySlug(string slug)
        {
            if (string.IsNullOrEmpty(slug))
            {
                return ShowMsg("请指定要查看的Post的Id或标题");
            }

            Post post = Post.Posts.Find(delegate(Post p)
            {
                return Utils.RemoveIllegalCharacters(slug).Equals(Utils.RemoveIllegalCharacters(p.Slug), StringComparison.OrdinalIgnoreCase);
            });

            if (null != post)
            {
                PageTitle = post.Title;
                GetCommentCookie();
                return View("Post", post);
            }
            else
            {
                return ShowMsg("很抱歉,你要查看的文章不存在.");
            }
        }
        #endregion

        #region 显示指定Category的文章列表
        /// <summary>
        /// 显示指定Category的文章列表
        /// </summary>
        [ActionName("Category")]
        public ActionResult ShowCategory(string id)
        {
            if (string.IsNullOrEmpty(id))
            {
                Response.Redirect("~/", true);
            }

            Guid categoryId = new Guid(id);
            List<IPublishable> posts = BlogEngine.Core.Post.GetPostsByCategory(categoryId).ConvertAll(new Converter<Post, IPublishable>(delegate(Post p) { return p as IPublishable; }));
            PageTitle = BlogEngine.Core.Category.GetCategory(categoryId).Title;

            return View(posts);
        }

        /// <summary>
        /// 显示指定Category的文章列表
        /// </summary>
        [ActionName("CategoryBySlug")]
        public ActionResult ViewCategoryBySlug(string slug)
        {
            if (string.IsNullOrEmpty(slug))
            {
                return ShowMsg("请指定要查看的Post的Id或标题");
            }

            Category category = Category.Categories.Find(delegate(Category c)
            {
                return Utils.RemoveIllegalCharacters(slug).Equals(Utils.RemoveIllegalCharacters(c.Title), StringComparison.OrdinalIgnoreCase);
            });

            if (null != category)
            {
                PageTitle = category.Title;

                List<IPublishable> posts = BlogEngine.Core.Post.GetPostsByCategory(category.Id).ConvertAll(new Converter<Post, IPublishable>(delegate(Post p) { return p as IPublishable; }));
                return View("Category", posts);
            }
            else
            {
                return ShowMsg("很抱歉,你要查看的分类不存在.");
            }
        }
        #endregion

        #region 显示指定Tag的文章列表
        /// <summary>
        /// 显示指定Tag的文章列表
        /// </summary>
        public ActionResult Tag(string id)
        {
            if (string.IsNullOrEmpty(id))
            {
                Response.Redirect("~/", true);
            }

            List<IPublishable> posts = BlogEngine.Core.Post.GetPostsByTag(id).ConvertAll(new Converter<Post, IPublishable>(delegate(Post p) { return p as IPublishable; }));
            PageTitle = "Tag '" + id + "' 下的随笔";

            return View(posts);
        }
        #endregion

        #region 添加评论

        [AcceptVerbs(HttpVerbs.Post|HttpVerbs.Put), CallByAjax(false)]
        public ActionResult AddComment(FormCollection form)
        {
            Comment comment = new Comment();
            string postId = form["comment_post_ID"] ?? "";
            Post post = Post.GetPost(new Guid(postId));
            if (TryUpdateModel(comment, new[] { "Content", "Author", "Email" }))
            {
                if (comment.IsValid)
                {
                    comment.Id = Guid.NewGuid();
                    comment.Author = Server.HtmlEncode(comment.Author);
                    //comment.Email = email;
                    comment.Content = Server.HtmlEncode(comment.Content);
                    comment.IP = Request.UserHostAddress;
                    //comment.Country = country;
                    comment.DateCreated = DateTime.Now;
                    comment.Parent = post;
                    comment.IsApproved = !BlogSettings.Instance.EnableCommentsModeration;

                    if (User.Identity.IsAuthenticated)
                        comment.IsApproved = true;

                    string website = form["Website"] ?? "";
                    if (website.Trim().Length > 0)
                    {
                        if (!website.ToLowerInvariant().Contains("://"))
                            website = "http://" + website;

                        Uri url;
                        if (Uri.TryCreate(website, UriKind.Absolute, out url))
                            comment.Website = url;
                    }

                    //if (notify && !Post.NotificationEmails.Contains(email))
                    //    Post.NotificationEmails.Add(email);
                    //else if (!notify && Post.NotificationEmails.Contains(email))
                    //    Post.NotificationEmails.Remove(email);

                    post.AddComment(comment);
                    SetCommentCookie(comment.Author, comment.Email, website, comment.Country);
                    return RedirectToRoute(new { controller = "Home", action = "Post", id = postId });
                }
                else
                {
                    foreach (string key in comment.BrokenRules.Keys)
                    {
                        ViewData.ModelState.AddModelError(key, comment.BrokenRules[key]);
                    }
                }
            }

            return View("Post", post);
        }

        [AcceptVerbs(HttpVerbs.Post | HttpVerbs.Put), CallByAjax(true)]
        public ActionResult AddCommentByAjax(FormCollection form)
        {
            JsonResultData jsonData = new JsonResultData();
            Comment comment = new Comment();
            string postId = form["comment_post_ID"] ?? "";
            Post post = Post.GetPost(new Guid(postId));
            if (TryUpdateModel(comment, new[] { "Content", "Author", "Email" }))
            {
                if (comment.IsValid)
                {
                    comment.Id = Guid.NewGuid();
                    comment.Author = Server.HtmlEncode(comment.Author);
                    //comment.Email = email;
                    comment.Content = Server.HtmlEncode(comment.Content);
                    comment.IP = Request.UserHostAddress;
                    //comment.Country = country;
                    comment.DateCreated = DateTime.Now;
                    comment.Parent = post;
                    comment.IsApproved = !BlogSettings.Instance.EnableCommentsModeration;

                    if (User.Identity.IsAuthenticated)
                        comment.IsApproved = true;

                    string website = form["Website"] ?? "";
                    if (website.Trim().Length > 0)
                    {
                        if (!website.ToLowerInvariant().Contains("://"))
                            website = "http://" + website;

                        Uri url;
                        if (Uri.TryCreate(website, UriKind.Absolute, out url))
                            comment.Website = url;
                    }

                    //if (notify && !Post.NotificationEmails.Contains(email))
                    //    Post.NotificationEmails.Add(email);
                    //else if (!notify && Post.NotificationEmails.Contains(email))
                    //    Post.NotificationEmails.Remove(email);

                    post.AddComment(comment);
                    SetCommentCookie(comment.Author, comment.Email, website, comment.Country);
                    return PartialView("_commentList", post.Comments);
                }
                else
                {
                    foreach (string key in comment.BrokenRules.Keys)
                    {
                        jsonData.ErrorMsg.Add(comment.BrokenRules[key]);
                    }
                }
            }
            jsonData.IsError = true;
            return Json_Net(jsonData);
        }

        #region Cookies

        /// <summary>
        /// Sets a cookie with the entered visitor information
        /// so it can be prefilled on next visit.
        /// </summary>
        private void SetCommentCookie(string name, string email, string website, string country)
        {
            HttpCookie cookie = new HttpCookie("comment");
            cookie.Expires = DateTime.Now.AddMonths(24);
            cookie.Values.Add("author", Server.UrlEncode(name));
            cookie.Values.Add("email", email);
            cookie.Values.Add("website", website);
            cookie.Values.Add("country", country);
            Response.Cookies.Add(cookie);
        }

        /// <summary>
        /// Gets the cookie with visitor information if any is set.
        /// Then fills the contact information fields in the form.
        /// </summary>
        private void GetCommentCookie()
        {
            HttpCookie cookie = Request.Cookies["comment"];
            try
            {
                if (cookie != null)
                {
                    ViewData["comment.author"] = Server.UrlDecode(cookie.Values["author"]);
                    ViewData["comment.email"] = cookie.Values["email"];
                    ViewData["comment.website"] = cookie.Values["website"];
                    ViewData["comment.country"] = cookie.Values["country"];
                    //this.SetFlagImageUrl();
                }
                else if (User.Identity.IsAuthenticated)
                {
                    MembershipUser user = Membership.GetUser();
                    ViewData["comment.author"] = user.UserName;
                    ViewData["comment.email"] = user.Email;
                    ViewData["comment.website"] = Request.Url.Host;
                }
            }
            catch (Exception)
            {
                // Couldn't retrieve info on the visitor/user
            }
        }

        #endregion

        #endregion

        #region 关于
        public ActionResult About()
        {
            PageTitle = Translate("AboutMe");

            return View();
        }
        #endregion
    }
}
